SyntacticExpression:
    Empty
    QuoteString (value : StringLiteral)
    NameReference (name : Identifier)
    Kleene (operand : SyntacticExpression)
    Optional (operand : SyntacticExpression)
    Positive (operand : SyntacticExpression)
    Sequence (operand : SyntacticExpression, isNullable : bool, separator : StringLiteral)
    Concat (left : SyntacticExpression, right : SyntacticExpression)
    Union (left : SyntacticExpression, right : SyntacticExpression)

SyntacticRuleDeclarator = (
    pattern : SyntacticExpression,
    precedence : TokenReference?,
    action : SemanticAction?
)

SyntacticDeclarator = (
    name : Identifier,
    `type` : TypeExpression?,
    rules : [SyntacticRuleDeclarator]
)

SyntacticDeclaration = (declarators : [SyntacticDeclarator])

%%

PrimarySyntacticExpression as SyntacticExpression:
    QuoteStringLiteral => SyntacticExpression.NewQuoteString($1, @1)
    Name => SyntacticExpression.NewNameReference($1, @1)
    '(' ')' => SyntacticExpression.NewEmpty(@@)
    '(' SyntacticExpression ')' => $2

PostfixSyntacticExpression as SyntacticExpression:
    PrimarySyntacticExpression => $1
    PostfixSyntacticExpression '*' => SyntacticExpression.NewKleene($1, @@)
    PostfixSyntacticExpression '?' => SyntacticExpression.NewOptional($1, @@)
    PostfixSyntacticExpression '+' => SyntacticExpression.NewPositive($1, @@)
    PostfixSyntacticExpression '%' QuoteStringLiteral => SyntacticExpression.NewSequence($1, True, $3, @@)
    PostfixSyntacticExpression '%+' QuoteStringLiteral => SyntacticExpression.NewSequence($1, False, $3, @@)

ConcatSyntacticExpression as SyntacticExpression:
    PostfixSyntacticExpression => $1
    ConcatSyntacticExpression PostfixSyntacticExpression => SyntacticExpression.NewConcat($1, $2, @@)

SyntacticExpression as SyntacticExpression:
    ConcatSyntacticExpression => $1
    SyntacticExpression '|' ConcatSyntacticExpression => SyntacticExpression.NewUnion($1, $3, @@)

SyntacticRuleDeclarator as SyntacticRuleDeclarator:
    SyntacticExpression NewLine => SyntacticRuleDeclarator.New($1, None, None, @@)
    SyntacticExpression '%prec' TokenReference NewLine => SyntacticRuleDeclarator.New($1, $3, None, @@)
    SyntacticExpression '%prec' TokenReference SemanticAction => SyntacticRuleDeclarator.New($1, $3, $4, @@)
    SyntacticExpression SemanticAction => SyntacticRuleDeclarator.New($1, None, $2, @@)
    '%prec' TokenReference NewLine => SyntacticRuleDeclarator.New(SyntacticExpression.NewEmpty(@@), $2, None, @@)
    '%prec' TokenReference SemanticAction => SyntacticRuleDeclarator.New(SyntacticExpression.NewEmpty(@@), $2, $3, @@)
    SemanticAction => SyntacticRuleDeclarator.New(SyntacticExpression.NewEmpty(@@), None, $1, @@)

SyntacticDeclarator as SyntacticDeclarator:
    Name ':' 'pass' NewLine => SyntacticDeclarator.New($1, None, default([SyntacticRuleDeclarator]), @@)
    Name ':' NewLine Indent 'pass' NewLine Unindent => SyntacticDeclarator.New($1, None, default([SyntacticRuleDeclarator]), @@)
    Name ':' NewLine Indent SyntacticRuleDeclarator+ Unindent => SyntacticDeclarator.New($1, None, $5, @@)
    Name 'as' TypeExpression 'pass' NewLine => SyntacticDeclarator.New($1, $3, default([SyntacticRuleDeclarator]), @@)
    Name 'as' TypeExpression ':' NewLine Indent 'pass' NewLine Unindent => SyntacticDeclarator.New($1, $3, default([SyntacticRuleDeclarator]), @@)
    Name 'as' TypeExpression ':' NewLine Indent SyntacticRuleDeclarator+ Unindent => SyntacticDeclarator.New($1, $3, $7, @@)

SyntacticDeclaration as SyntacticDeclaration:
    SyntacticDeclarator* => SyntacticDeclaration.New($1, @@)
